package com.tools;

import java.util.Collections;
import java.util.Comparator;
import java.util.Vector;

import android.os.Handler;
import android.util.Log;

@SuppressWarnings({"rawtypes", "unchecked"})
public abstract class AsynSingleTaskEx<Params, Progress, Result> {

	public static final int MIN_PRIORITY = 0;
	Params[] mParams;
	Progress[] mProgresses;
	Result mResult;
	static Vector mBuffer;
	static AsynSingleTaskEx mAsynSingleTaskEx;
	static Handler mPostHandler;

	enum TaskState {

		wait, runing, pause, end
	}

	TaskState mState = TaskState.wait;

	public int mPriority;
	static boolean isLive = true;

	private void sort() {

		synchronized (mBuffer) {
			Collections.sort(mBuffer, new Comparator() {

				public int compare(Object lhs, Object rhs) {

					AsynSingleTaskEx left = (AsynSingleTaskEx) lhs;
					AsynSingleTaskEx right = (AsynSingleTaskEx) rhs;

					if (left.mPriority > right.mPriority) {
						return -1;
					}
					return 0;
				}
			});
			
			for(int i =0;i<mBuffer.size();i++){
				Log.i("mPriority","mPriority = " + ((AsynSingleTaskEx)mBuffer.get(i)).mPriority);
			}
			
		}

	}

	public AsynSingleTaskEx() {

		if (mPostHandler == null) {
			mPostHandler = new Handler();
			mBuffer = new Vector();

			new Thread() {

				public void run() {
					try {
						runing();
					} catch (Exception e) {
						// TODO: handle exception
					}

				};
			}.start();

		}

	}

	private void runing() throws InterruptedException {

		while (isLive) {

			if (mBuffer.size() > 0) {
				
				mAsynSingleTaskEx = (AsynSingleTaskEx) mBuffer.firstElement();
				Log.i("mAsynSingleTaskEx",
						"mAsynSingleTaskEx = " + mAsynSingleTaskEx.mState);

				if (mAsynSingleTaskEx.mState == TaskState.wait) {

					mAsynSingleTaskEx.mState = TaskState.runing;
					mAsynSingleTaskEx.mResult = mAsynSingleTaskEx
							.doInBackground(mAsynSingleTaskEx.mParams);

				} else if (mAsynSingleTaskEx.mState == TaskState.pause) {

					mAsynSingleTaskEx.mState = TaskState.runing;

					mAsynSingleTaskEx
							.onResumeBackground(mAsynSingleTaskEx.mParams);

					mPostHandler.post(new Runnable() {

						public void run() {
							if (mAsynSingleTaskEx != null)
								mAsynSingleTaskEx
										.onPostResume(mAsynSingleTaskEx.mProgresses);
						}
					});

				}

				if (mAsynSingleTaskEx.mState == TaskState.runing) {
					
						mPostHandler.post(new Runnable() {

							public void run() {
								synchronized(mAsynSingleTaskEx){
									Log.i("mResult",
											"mAsynSingleTaskEx = " + mAsynSingleTaskEx.mState);
									mAsynSingleTaskEx
											.onPostExecute(mAsynSingleTaskEx.mResult);
								}
							}
						});
						mBuffer.removeElement(mAsynSingleTaskEx);
						mAsynSingleTaskEx.mState = TaskState.end;
				}

			} 
			Thread.sleep(1000);

		}

	}

	public final void execute(int priority, Params... params) {
		this.mPriority = priority;
		this.mParams = params;

		if (mBuffer.indexOf(this) > -1) {
			return;
		}
		mBuffer.addElement(this);
		sort();

		mPostHandler.post(new Runnable() {

			public void run() {
				onPostPreExecute();
			}
		});

		if (mAsynSingleTaskEx != null) {
			synchronized (mAsynSingleTaskEx) {
				AsynSingleTaskEx firstTaskEx = (AsynSingleTaskEx) mBuffer
						.firstElement();
				if (firstTaskEx.mPriority > mAsynSingleTaskEx.mPriority) {

					mAsynSingleTaskEx.mState = TaskState.pause;
					mAsynSingleTaskEx.onPause(mAsynSingleTaskEx.mProgresses);
					mPostHandler.post(new Runnable() {

						public void run() {
							mAsynSingleTaskEx
									.onPostPause(mAsynSingleTaskEx.mProgresses);
						}
					});

				}

			}
		}

	}

	public abstract void onResumeBackground(Params... params) ;
	
	protected abstract void onPause(Progress... values);

	protected abstract Result doInBackground(Params... params) ;

	protected void onPostCancelled(Result result) {

	}

	protected void onPostPause(Progress... values) {

	}

	protected void onPostResume(Progress... values) {

	}

	// 执行前
	protected void onPostPreExecute() {
	}

	// 执行后
	protected void onPostExecute(Result result) {
	}

	public void onPostProgressUpdate(Progress... values) {

	}

	public final void updateProgress(final Progress... values) {
		mPostHandler.post(new Runnable() {

			public void run() {
				onPostProgressUpdate(values);
			}
		});
	}

	public static int getMaxPriority() {
		if (mAsynSingleTaskEx != null) {
			return mAsynSingleTaskEx.mPriority;
		}
		return MIN_PRIORITY;
	}

	public static int getMinPriority() {

		return MIN_PRIORITY;
	}

	public static int getBufferSize() {

		return 0;
	}

}
